package com.szz.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.security.oauth2.provider.token.store.KeyStoreKeyFactory;

import javax.annotation.Resource;
import java.security.KeyPair;

@Configuration  //标记为我们自己的配置类
public class AuthorizationConfig extends AuthorizationServerConfigurerAdapter {


//    /**
//     * 描述: 注入jwt的token转换
//     *
//     * @param null:
//     * @return
//     */
//    @Autowired
//    private JwtAccessTokenConverter jwtAccessTokenConverter;

    @Resource
    private BCryptPasswordEncoder passwordEncoder;

    //注入redis的连接工厂
    @Autowired
    private RedisConnectionFactory redisConnectionFactory;

    /**
     * 描述: 注入认证管理器
     *
     * @return
     */
    @Autowired
    private AuthenticationManager authenticationManager;

//    /**
//     * 描述: 创建一个redis的tokenStore存放颁发的token
//     */
//    @Bean
//    public TokenStore tokenStore() {
//        return new RedisTokenStore(redisConnectionFactory);
//    }

    /**
     * 使用jwt存储token
     *
     * @return
     */
    @Bean
    public TokenStore tokenStore() {
//        return new JwtTokenStore(jwtAccessTokenConverter);
    return new JwtTokenStore( accessTokenConverter());
    }

//    /**
//     * 描述: 创建jwt的token转换器，签名先试用对称加密
//     *
//     * @param :
//     * @return org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter
//     */
//    @Bean
//    public JwtAccessTokenConverter jwtAccessTokenConverter() {
//        JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
//        jwtAccessTokenConverter.setSigningKey("bjpowernode-oauth2.0");
//        return jwtAccessTokenConverter;
//    }
@Bean
public JwtAccessTokenConverter accessTokenConverter() {
    //使用非对称加密，只要私钥不泄密，别人无法生成token，公钥只能验证token
    JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
    //将文件加载进来
    ClassPathResource resource = new ClassPathResource("rsa/cxs-jwt.jks");
    //得到keyStore
    KeyStoreKeyFactory keyFactory = new KeyStoreKeyFactory(resource, "cxs123".toCharArray());
    //往转换器里设置私钥
    KeyPair keyPair = keyFactory.getKeyPair("cxs-jwt");
    jwtAccessTokenConverter.setKeyPair(keyPair);
//        jwtAccessTokenConverter.setSigningKey("bjpowernode-oauth2.0");
    return jwtAccessTokenConverter;
}
    /*
         第三方的账号配置信息
      */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {

        //在内存中配置第三方的账号信息(授权账号信息)
        clients.inMemory()
                //第三方用户名
                .withClient("web")
                //账号的密码
                .secret(passwordEncoder.encode("web-secret"))
                //token的过期时间，以秒为单位
                .accessTokenValiditySeconds(7200)
                //作用域
                .scopes("web-scopes")
                //授权方式：**验证码授权(第三方、微信)**、静默授权、**客户端授权**、**密码授权**
                .authorizedGrantTypes("authorization_code")//验证码授权方式
                //重定向的地址，用于获取令牌
                .redirectUris("https://www.baidu.com")
                .and()
                .withClient("ios")
                .accessTokenValiditySeconds(7200)
                .secret(passwordEncoder.encode("ios-secret"))
                .scopes("ios-scopes")
                .authorizedGrantTypes("implicit")//静默授权
                .redirectUris("https://www.baidu.com")
                .and()
                //密码授权方式，必须要配置认证管理器
                .withClient("api")
                .secret(passwordEncoder.encode("api-secret"))
                .scopes("api-scopes")
                .accessTokenValiditySeconds(7200)
                .authorizedGrantTypes("password")//密码授权
                .redirectUris("https://www.baidu.com")
                .and()
                .withClient("client")
                .secret(passwordEncoder.encode("client-secret"))
                .scopes("client-scopes")
                .accessTokenValiditySeconds(7200)
                .authorizedGrantTypes("client_credentials")//客户端授权
                .redirectUris("https://www.baidu.com")
        ;
    }

    /**
     * 描述: token的存储方式 我们先存在redis里面
     *
     * @param endpoints:
     * @return void
     */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
//        //使用redis做token的存储
//        endpoints.tokenStore(tokenStore());
//        //使用redis做token的存储,密码授权必须要认证管理器
//        endpoints.tokenStore(tokenStore()).authenticationManager(authenticationManager);
            //使用jwt做token存储
        endpoints.tokenStore(tokenStore())
                .authenticationManager(authenticationManager)
                .accessTokenConverter(accessTokenConverter())
        ;
    }
}
